home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / utility / freedos.zip / COM050.ZIP / COMMAND.C < prev    next >
C/C++ Source or Header  |  1996-01-17  |  14KB  |  665 lines

  1. /*
  2.  *  COMMAND.C - command-line interface.
  3.  *
  4.  *  Version: 0.50
  5.  *
  6.  *  Comments:
  7.  *
  8.  *  06/17/94 (Tim Norman) ---------------------------------------------------
  9.  *    started.
  10.  *
  11.  *  08/08/95 (Matt Rains) ---------------------------------------------------
  12.  *    i have cleaned up the source code. changes now bring this source into
  13.  *    guidelines for recommended programming practice.
  14.  *
  15.  *    i have added the the standard FreeDOS GNU licence test to the
  16.  *    initialize() function.
  17.  *
  18.  *    i have started to replease puts() with printf(). this will help
  19.  *    standardize output. please follow my lead.
  20.  *
  21.  *    i have added some constants to help making changes easier.
  22.  *
  23.  *  12/15/95 (Tim Norman) ---------------------------------------------------
  24.  *    major rewrite of the code to make it more efficient and add
  25.  *    redirection support (finally!)
  26.  *
  27.  *  1/6/96 (Tim Norman) -----------------------------------------------------
  28.  *    finished adding redirection support!!!  Changed to use our own exec
  29.  *    code (MUCH thanks to Svante Frey!!
  30.  *
  31.  */
  32.  
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <ctype.h>
  36. #include <string.h>
  37. #include <dos.h>
  38. #include <process.h>
  39. #include <time.h>
  40. #include <errno.h>
  41. #include <dir.h>
  42. #include <fcntl.h>
  43. #include <io.h>
  44. #include <sys\stat.h>
  45.  
  46. #include "command.h"
  47.  
  48. #define DEBUG
  49.  
  50. #define SYNTAXERR "ERROR: syntax error"
  51. #define NOENVERR  "ERROR: no environment"
  52.  
  53. #define INVALIDDRIVE    "ERROR: invalid drive"
  54. #define INVALIDFUNCTION "ERROR: invalid function"
  55. #define FILENOTFOUND    "ERROR: file not found"
  56. #define ACCESSDENIED    "ERROR: access denied"
  57. #define NOTENOUGHMEMORY "ERROR: not enough memory"
  58. #define BADENVIROMENT   "ERROR: bad enviroment"
  59. #define BADFORMAT       "ERROR: bad format"
  60. #define ERROR_E2BIG    "ERROR: Argument list too long"
  61. #define ERROR_EINVAL    "ERROR: Invalid argument"
  62.  
  63. #define PROMPT    "prompt"
  64.  
  65. #define EXIT      "exit"
  66. #define CD        "cd"
  67. #define DOSKEY    "doskey"
  68. #define DIR       "dir"
  69. #define REM       "rem"
  70. #define SET       "set"
  71. #define VER       "ver"
  72. #define MD        "md"
  73. #define RD        "rd"
  74. #define DEL       "del"
  75. #define REN       "ren"
  76.  
  77. char exitflag = 0;      /* indicates EXIT was typed */
  78. char canexit = 1;       /* indicates if this shell is exitable */
  79.  
  80. /*
  81.  *  fatal error handler.
  82.  *
  83.  *
  84.  */
  85. void fatal_error(char *s)
  86. {
  87.    printf("fatal_error() : %s\n", s);
  88.    exit(100);
  89. }
  90.  
  91. /*
  92.  *  is character a delimeter when used on first word?
  93.  *
  94.  *
  95.  */
  96. char is_delim(char c)
  97. {
  98.    return(c == '/' || c == '=' || c == 0 || isspace (c));
  99. }
  100.  
  101. /*
  102.  *  strip the extra spaces between parameters on command-line. quotation
  103.  *  mark aware.
  104.  *
  105.  */
  106. int strip(char *command)
  107. {
  108.    unsigned char place = 0;
  109.    unsigned char tempplace = 0;
  110.    unsigned char firstword = 1;
  111.    unsigned char inquote = 0;
  112.    char temp[128] = "";
  113.    char foundspace = 0;
  114.  
  115.    while(isspace(command[place]))
  116.    {
  117.       place++;
  118.    }
  119.  
  120.    while(command[place])
  121.    {
  122.       if(foundspace && !isspace(command[place]))
  123.       {
  124.          temp[tempplace++] = ' ';
  125.          foundspace = 0;
  126.       }
  127.  
  128.       if (isspace (command[place]) && !inquote)
  129.       {
  130.          foundspace = 1;
  131.          firstword = 0;
  132.       }
  133.       else if(is_delim(command[place]) && firstword)
  134.       {
  135.          temp[tempplace++] = ' ';
  136.          temp[tempplace++] = command[place];
  137.       }
  138.       else if (command[place] == '"')
  139.       {
  140.          if(!inquote && place > 0 && !isspace(command[place - 1]))
  141.      {
  142.             temp[tempplace++] = ' ';
  143.          }
  144.  
  145.          temp[tempplace++] = '"';
  146.          inquote = !inquote;
  147.  
  148.          if(!inquote && !isspace(command[place + 1]))
  149.          {
  150.             temp[tempplace++] = ' ';
  151.          }
  152.       }
  153.       else
  154.       {
  155.          temp[tempplace++] = command[place];
  156.       }
  157.  
  158.       place++;
  159.    }
  160.  
  161.    temp[tempplace] = 0;
  162.    strcpy(command, temp);
  163.  
  164.    if(inquote)
  165.    {
  166.       return(0);
  167.    }
  168.    else
  169.    {
  170.       return(1); /* true on success */
  171.    }
  172. }
  173.  
  174. /*
  175.  *  split the command-line into parameters. works with quotation marks.
  176.  *
  177.  *
  178.  */
  179. unsigned char split(char *command, char *p[128])
  180. {
  181.    unsigned char count;
  182.    unsigned char place = 1;
  183.    unsigned char len;
  184.    unsigned char inquote = 0;
  185.  
  186.    p[0] = command;
  187.    len = strlen (command);
  188.  
  189.    for(count = 0; count < len; count++)
  190.    {
  191.       if(command[count] == '"')
  192.       {
  193.          inquote = !inquote;
  194.       }
  195.       else if(isspace (command[count]) && !inquote)
  196.       {
  197.          command[count] = 0;
  198.      p[place++] = &command[count + 1];
  199.       }
  200.    }
  201.  
  202.    p[place] = NULL;
  203.    return(place);
  204. }
  205.  
  206. /* returns TRUE if the char is a delimiter char (i.e. can't be in a filename) */
  207. char is_special(char ch)
  208. {
  209.    return(ch == '<' || ch == '>' || ch == '=' || ch == ',' || ch == ';' ||
  210.       ch == ':' || ch == '*' || ch == '?' || ch == '[' || ch == ']' ||
  211.       ch == '/' || ch == '\\'|| ch == '+' || ch == '"' || ch <= ' ' ||
  212.       ch == '|');
  213. }
  214.  
  215. /*
  216.  * execute this as an external program
  217.  *
  218.  *
  219. */
  220. void execute (char *s)
  221. {
  222.    char cmd[128], *p[128], *paths[129], fullname[128];
  223.    int args, r;
  224.  
  225.    /* vars needed for the new EXEC stuff */
  226.    char *start;
  227.  
  228.    strcpy (cmd, s);
  229.  
  230.    if (!strip (cmd))
  231.    {
  232.       fprintf (stderr, "%s\n", SYNTAXERR);   /* unmatched quotes */
  233.       return;
  234.    }
  235.  
  236.    args = split (cmd, p);
  237.  
  238.    /* check this for shortcut commands and the like */
  239.    if(p[0][0] && p[0][1] == ':' && p[0][2] == 0) /* change drives */
  240.    {
  241.       if(isalpha(p[0][0]))
  242.       {
  243.      setdisk(toupper(p[0][0]) - 'A');
  244.       }
  245.  
  246.       if(getdisk () != toupper(p[0][0]) - 'A')
  247.       {
  248.      printf("%s\n", INVALIDDRIVE);
  249.       }
  250.       return;
  251.    }
  252.    else if (memicmp (p[0], CD, 2) == 0 && (p[0][2] == '\\' || p[0][2] == '.'))
  253.    {
  254.       cd(args, p, s);
  255.       return;
  256.    }
  257.    else if (memicmp (p[0], MD, 2) == 0 && (p[0][2] == '\\' || p[0][2] == '.'))
  258.    {
  259.       md(args, p, s);
  260.       return;
  261.    }
  262.    else if (memicmp (p[0], RD, 2) == 0 && (p[0][2] == '\\' || p[0][2] == '.'))
  263.    {
  264.       rd(args, p, s);
  265.       return;
  266.    }
  267.  
  268.    /* we need to search OUR path for the binary... use my searching algo */
  269.    get_paths(paths);
  270.  
  271.    if(!find_which(paths, p[0], fullname))
  272.    {
  273.       fprintf(stderr, "%s\n", FILENOTFOUND);
  274.       return;
  275.    }
  276.  
  277.    start = s; /* point to command-line params */
  278.  
  279.    while(isspace(*start))
  280.    {
  281.       start++;
  282.    }
  283.  
  284.    while(*start != 0 && !is_delim (*start))
  285.    {
  286.       start++;
  287.    }
  288.  
  289.    while(isspace(*start))
  290.    {
  291.       start++;
  292.    }
  293.  
  294.    if(!stricmp(strrchr(fullname,'.') + 1, "bat"))
  295.    {
  296.       batch(fullname, args, p);
  297.    }
  298.    else if((r = exec(fullname, start, EnvSeg)) != 0)
  299.    {
  300.       switch(r)
  301.       {
  302.      case 1 :
  303.      {
  304.         printf("%s\n", INVALIDFUNCTION);
  305.         break;
  306.      }
  307.      case 2 :
  308.      {
  309.         printf("%s\n", FILENOTFOUND);
  310.         break;
  311.      }
  312.      case 5 :
  313.      {
  314.         printf("%s\n", ACCESSDENIED);
  315.         break;
  316.      }
  317.      case 8 :
  318.      {
  319.         printf("%s\n", NOTENOUGHMEMORY);
  320.         break;
  321.      }
  322.      case 10 :
  323.      {
  324.         printf("%s\n", BADENVIROMENT);
  325.         break;
  326.      }
  327.      case 11 :
  328.      {
  329.         printf("%s\n", BADFORMAT);
  330.         break;
  331.      }
  332.      default :
  333.      {
  334.         printf("ERROR: unknown error %d.\n", errno);
  335.         break;
  336.      }
  337.       }
  338.    }
  339. }
  340.  
  341. /* move this somewhere else later */
  342. static struct CMD
  343. {
  344.    char *name;
  345.    void (*func)(int, char *[128], char *);
  346. } cmds[] = { { "DIR", dir },
  347.          { "CD", cd },
  348.          { "RD", rd },
  349.          { "MD", md },
  350.          { "DEL", del },
  351.          { "REN", ren },
  352.          { "REM", rem },
  353.          { "DOSKEY", doskey },
  354.          { "EXIT", internal_exit },
  355.          { "VER", ver },
  356.          { "SET", set },
  357.          { "PROMPT", prompt },
  358.          { "LH", loadhigh },
  359.          { "LOADHIGH", loadhigh },
  360.          { "LOADFIX", loadfix },
  361.          { NULL, NULL } };
  362.  
  363. /*
  364.  * run this command
  365.  *
  366.  *
  367.  */
  368. void command (char *s)
  369. {
  370.    char line[256];    /* just a little extra space :) */
  371.    char com[128];     /* the first word in the command */
  372.    int count, start;
  373.    int executed = 0;  /* whether the command was executed */
  374.  
  375.    strcpy (line, s);
  376.